use core::{fmt, slice};
use std::{borrow::{Borrow, BorrowMut}, cell::RefCell, cmp::Ordering, collections::{btree_map::Values, HashMap}, fs::{self, File}, io::{self, stdout, BufRead, BufReader, BufWriter, Read, Write}, net::{TcpListener, TcpStream}, ops::{Add, Deref}, path::{self, Display}, process::Output, rc::{Rc, Weak}, result, sync::{mpsc, Arc, Mutex}, thread, time::Duration, vec};
use ferris_says::say;
use rand::Rng;
use guessing_game as gsgame;
use rust_learn::{self, closure_exercise, draw_ui};
use hello_macro::HelloMacro;
use hello_macro_derive::HelloMacro;

mod guessing_game;
mod blog;

#[cfg(test)]
mod test_mod {
    #[test]
    fn test_lifetime() {
        assert_ne!(1, 1);
    }

    #[test]
    fn test_plus_one() {
        let result = 1 + 2;
        assert_eq!(result, 3);
        assert_ne!(result, 5);
    }
}

static GLOBAL_HELLO_WOLRD: &str = "asdf";

static mut CNT: i32 = 1;

fn main() {
    single_thread_web_server();
}

fn single_thread_web_server() {
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    for stream in listener.incoming() {
        let stream = stream.unwrap();
        thread::spawn(|| handle_connection(stream));
    } 
}

fn handle_connection(mut stream: TcpStream) {
    let buf_reader = BufReader::new(&stream);
    let http_request: Vec<_> = buf_reader
    .lines()
    .map(|result| result.unwrap())
    .take_while(|line| !line.is_empty())
    .collect();
    println!("Request: {:#?}", http_request);
    let first_line = &http_request[0];

    let (status_line, file_name) = match &first_line[..] {
        "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"),
        "GET /suspend HTTP/1.1" => {
            thread::sleep(Duration::from_millis(5000));
            ("HTTP/1.1 200 OK", "hello.html")
        },
        _ => ("HTTP/1.1 404 NOT FOUND", "404.html")
    };
    
    let contents = fs::read_to_string(&file_name).unwrap();
    let content_length = contents.len();
    let response = format!("{status_line}\r\nContent-Length: {content_length}\r\n\r\n{contents}");
    stream.write_all(response.as_bytes()).unwrap();
}

#[derive(HelloMacro)]
struct Pancakes;

fn macro_exercise() {
    let x = vec![1, 2, 3];
    let y = [1, 2, 3];
    test_macro!("123");
    Pancakes::hello_macro();
}

#[macro_export]
macro_rules! test_macro {
    ($e:expr) => {
        println!("{:?}", $e);
    }
}

fn advanced_trait_exercise() {
    // full qualified syntax for disambiguation
    let player = Human;
    player.fly();
    Pilot::fly(&player);
    Wizard::fly(&player);

    let dog = Dog;

    println!("A baby dog is called {}", Dog::baby_name());

    println!("A baby dog in animal is called {}", <Dog as Animal>::baby_name());

    let p1 = Point {x: 1, y: 2};
    p1.outline_print();

    let warpper_vec_str = WrapperVec(vec![String::from("Hello"), String::from("I am"), String::from("newtype pattern")]);
    println!("{warpper_vec_str}");
}

trait Pilot {
    fn fly(&self);
}

trait Wizard {
    fn fly(&self);
}

struct Human;

impl Pilot for Human {
    fn fly(&self) {
        println!("My plane, fly!");
    }
}

impl Wizard for Human {
    fn fly(&self) {
        println!("Up, fly!");
    }
}

impl Human {
    fn fly(&self) {
        println!("Jump, superman!");
    }
}

trait Animal {
    fn baby_name() -> String;
}

struct Dog;

impl Animal for Dog {
    fn baby_name() -> String {
        String::from("dog baby")
    }
}

impl Dog {
    fn baby_name() -> String {
        String::from("dot baby")
    }
}

trait OutlinePrint: fmt::Display {
    fn outline_print(&self) {
        let output = self.to_string();
        let len = output.len();
        println!("{}", "*".repeat(len + 4));
        println!("*{}*", " ".repeat(len + 2));
        println!("* {} *", output);
        println!("*{}*", " ".repeat(len + 2));
        println!("{}", "*".repeat(len + 4));
    }
}

impl fmt::Display for Point<i32, i32> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl OutlinePrint for Point<i32, i32> {
    fn outline_print(&self) {
        let output = self.to_string();
        let len = output.len();
        println!("{}", "*".repeat(len + 4));
        println!("*{}*", " ".repeat(len + 2));
        println!("* {} *", output);
        println!("*{}*", " ".repeat(len + 2));
        println!("{}", "*".repeat(len + 4));
    }
}

struct WrapperVec<T> (Vec<T>);

impl fmt::Display for WrapperVec<String> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}] ", self.0.join(", "))
    }
}

trait test<T> {
    fn test(a: T) -> T;
}

struct AItem {

}

impl test<String> for AItem {
    fn test(a: String) -> String {
        String::from("string impl")
    }
}

// impl<T> test<T> for AItem {
//     fn test(a: T) -> T {
//         a
//     }
// }

trait b_test {
    type Item;
    fn test() -> Self::Item;
}

impl b_test for AItem {
    type Item = String;

    fn test() -> Self::Item {
        String::from("")
    }
}

fn unsafe_exercise() {
    let mut num = 5;
    let x = &num as *const i32;
    let y = &mut num as *mut i32;

    let address = 0x012345usize;
    let ap = address as *const i32;

    unsafe {
        println!("x={}, y={}", *x, *y);
        *y = 1;
        println!("x={}, y={}", *x, *y);
        // println!("ap={}", *ap);
        dangerous();

        let mut v = vec![1, 5, 6, 7, 8, 9];
        let r = &mut v[..];
        let (a, b) = split_at_mut(r, 3);
        println!("a={:?}", a);
        println!("b={:?}", b);

        println!("abs = {}", abs(-3));

        println!("CNT = {CNT}");
        CNT = CNT + 1;
        println!("ADD CNT = {CNT}");
    }
}

fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = values.len();
    assert!(mid <= len);

    // let ptr = values as *mut [i32];
    let ptr = values.as_mut_ptr();
    unsafe {
        // (&mut (*ptr)[..mid], &mut (*ptr)[mid..])
        (slice::from_raw_parts_mut(ptr, mid), slice::from_raw_parts_mut(ptr.add(mid), len - mid))
    }
}

unsafe fn dangerous() {
    // arbitrary memory location
    let address = 0x012345usize;
    let p = address as *mut i32;

    // let Values: &[i32] = slice::from_raw_parts_mut(p, 10000);
    // println!("{:?}", Values);
}

extern "C" {
    fn abs(input: i32) -> i32;
}

fn pattern_exercise() {
    let x = Some(5);
    let y = 10;

    match x {
        Some(50) => println!("Got 50"),
        Some(y) => println!("inside match y = {y}"),
        _ => println!("Default case x = {:?}", x)
    }

    println!("outside match x={:?}, y={}", x, y);

    let z = 7;
    match z {
        1 | 2 => println!("1 | 2"),
        3..=10 => println!("3..=10"),
        _ => println!("Default")
    }

    let p1 = Point {
        x: 1,
        y: 3
    };
    let Point {x: a, y: b} = p1;
    let Point {x, y} = p1;
    println!("a={a}, b={b}");
    println!("x={x}, y={y}");


    let p2 = Point {
        x: 0,
        y: 3
    };
    match p2 {
        Point { x, y: 0 } => println!("On the x axis at {x}"),
        Point { x: 0, y } => println!("On the y axis at {y}"),
        Point { x, y } => {
            println!("On neither axis: ({x}, {y})");
        }
    }

    enum Message {
        Hello { id: i32 },
    }

    let msg = Message::Hello { id: 6 };

    match msg {
        // Message::Hello { id: idd @ 1..=10 } => println!("{idd}"),
        // Message::Hello {id} if id > 3 => println!("{id}"),
        Message::Hello {id: idd2 @ (2|6)} => println!("3 {idd2}"),
        _ => println!("default"),
    }

    // match msg {
    //     Message::Hello {
    //         id: id_variable @ 3..=7,
    //     } => println!("Found an id in range: {}", id_variable),
    //     Message::Hello { id: 10..=12 } => {
    //         println!("Found an id in another range")
    //     }
    //     Message::Hello { id } => println!("Found some other id: {}", id),
    // }
}

fn mutex_exercise() {
    let m = Mutex::new(5);

    {
        let mut num = m.lock().unwrap();
        *num = 6;
    }

    println!("m = {:?}", m);

    let m1 = Arc::new(Mutex::new(5));
    let thread1_m1 = Arc::clone(&m1);
    let job1 = thread::spawn(move|| {
        for i in 1..10 {
            println!("thread 1 turn {i}: getting lock");
            let num: std::sync::MutexGuard<'_, i32> = thread1_m1.lock().unwrap();
            println!("thread 1 turn {i}: getted lock.num={num}");
        }
    });

    let thread2_m1 = Arc::clone(&m1);
    let job2 = thread::spawn(move|| {
        for i in 1..10 {
            println!("thread 2 turn {i}: getting lock");
            let num: std::sync::MutexGuard<'_, i32> = thread2_m1.lock().unwrap();
            println!("thread 2 turn {i}: getted lock.num={num}");
        }
    });
    job1.join();
    job2.join();
}

fn channel_exercise() {
    let (tx, rx) = mpsc::channel();
    let tx1 = tx.clone();
    thread::spawn(move || {
        let x = String::from("hello, main, I'm spawn!");
        let msg_list = vec![String::from("hi"), String::from("I"), String::from("love"), String::from("you")];

        for msg in msg_list {
            tx1.send(msg).unwrap();
            thread::sleep(Duration::from_millis(10));
        }
    });

    thread::spawn(move || {
        let x = String::from("hello, main, I'm spawn!");
        let msg_list = vec![String::from("more"), String::from("msg"), String::from("in"), String::from("thread2")];

        for msg in msg_list {
            tx.send(msg).unwrap();
            thread::sleep(Duration::from_millis(10));
        }
    });
    
    for recv in rx {
        println!("Got: {recv}");
    }
}

fn concurrence_exercise() {
    thread::spawn(|| {
        for i in 1..10 {
            println!("count in spawn thread: {i}");
            thread::sleep(Duration::from_millis(100));
        }
    });

    let x = vec![1];

    let job = thread::spawn(move || {
        for i in 1..10 {
            println!("count in spawn thread with job: {i}");
            thread::sleep(Duration::from_millis(1));
        }
        println!("I need x: {:?}", x);
    });

    for i in 1..5 {
        println!("count in main thread: {i}");
        thread::sleep(Duration::from_millis(1));
    }

    job.join().unwrap();
}

#[derive(Debug)]
struct Node {
    value: i32,
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>
}

fn weak_ref_exercise() {
    let leaf = Rc::new(Node {
        value: 3,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![])
    });

    println!(
        "leaf parent = {:?}, strong = {}, weak = {}", leaf.parent.borrow().upgrade(), Rc::strong_count(&leaf), Rc::weak_count(&leaf));

    {
        let branch = Rc::new(Node {
            value: 5,
            parent: RefCell::new(Weak::new()),
            children: RefCell::new(vec![Rc::clone(&leaf)])
        });
        *leaf.parent.borrow_mut() = Rc::downgrade(&branch);

        println!(
            "branch strong = {}, weak = {}",
            Rc::strong_count(&branch),
            Rc::weak_count(&branch),
        );

        println!(
            "leaf strong = {}, weak = {}",
            Rc::strong_count(&leaf),
            Rc::weak_count(&leaf),
        );
    }

    println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
    println!(
        "leaf strong = {}, weak = {}",
        Rc::strong_count(&leaf),
        Rc::weak_count(&leaf));
}

#[derive(Debug)]
enum List2 {
    Cons(i32, RefCell<Rc<List2>>),
    Nil
}

impl List2 {
    fn tail(&self) -> Option<&RefCell<Rc<List2>>> {
        match self {
            Self::Cons(_, list) => Some(list),
            _ => None,
        }
    }
}

fn ref_cycle_exercise() {
    let a = Rc::new(List2::Cons(0, RefCell::new(Rc::new(List2::Nil))));

    println!("a initial rc cnt = {}", Rc::strong_count(&a));
    println!("a next item = {:?}", a.tail());

    let b = Rc::new(List2::Cons(0, RefCell::new(Rc::clone(&a))));

    println!("a rc count after b creation = {}", Rc::strong_count(&a));
    println!("b initial rc count = {}", Rc::strong_count(&b));
    println!("b next item = {:?}", b.tail());

    if let Some(link) = a.tail() {
        *link.borrow_mut() = Rc::clone(&b);
    }

    println!("a rc count after cycle = {}", Rc::strong_count(&a));
    println!("a next item = {:?}", a.tail());
    println!("b rc count after cycle = {}", Rc::strong_count(&b));
    println!("b next item = {:?}", b.tail());
}

fn refcell_exercise() {
    let x = 5;
    let y = RefCell::new(x);
    println!("y={}", y.borrow());
    let mut z = y.borrow_mut();
    *z = 6;
    println!("x={x}, z={}", z);
}

fn rc_exercise() {
    let d = List::Con(10, Rc::new(List::Nil));
    let a = Rc::new(List::Con(5, Rc::new(d)));
    println!("count after creating a = {}", Rc::strong_count(&a));
    {
        let b = List::Con(3, Rc::clone(&a));
        println!("count after creating a = {}", Rc::strong_count(&a));
    }
    println!("count after creating a = {}", Rc::strong_count(&a));
    let c = List::Con(1, Rc::clone(&a));
    println!("count after creating a = {}", Rc::strong_count(&a));
}

struct CustomSP {
    data: String
}

impl Drop for CustomSP {
    fn drop(&mut self) {
        println!("{} is dropped!", self.data);
    }
}

fn drop_exercise() {
    let a = CustomSP {
        data: String::from("a")
    };
    let b = CustomSP {
        data: String::from("b")
    };
    let c = CustomSP {
        data: String::from("c")
    };
    drop(b);
}

struct MyBox<T> (T);

impl<T> MyBox<T> {
    fn new(value: T) -> MyBox<T> {
        MyBox(value)
    }

    fn g_ref(&self) -> &MyBox<T> {
        self
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn deref_exercise() {
    let x = 5;
    let y = MyBox::new(x);

    assert_eq!(5, x);
    assert_eq!(5, *y);
}

fn smart_point_exercise() {
    let x = 5;
    let y = &x;
    let z = y + 1;

    println!("y = {y}, z = {z}");

    if *y == x {
        println!("equal must dereference");
    }

    let a = Box::new(x);
    if *a == x {
        println!("box can equal");
    }
}

enum List {
    Con(i32, Rc<List>),
    Nil
}

fn lifetime_exercise() {
    let r ;
    {
        let x = 5;
        r = &x;
        println!("r: {r}");
    }
    // println!("r: {r}");
}

pub trait Fly {
     fn fly(&self) -> f64;

     fn display_name(&self) -> String;
}

pub trait Quack {
    fn quack(&self) -> String;
}

struct Bird {
    bird_name: String,
    bird_type: String
}

impl Fly for Bird {
    fn fly(&self) -> f64 {
        300.0
    }

    fn display_name(&self) -> String {
        format!("{}[{}]", self.bird_name, self.bird_type)
    }
}

impl Quack for Bird {
    fn quack(&self) -> String {
        String::from("ga ga!")
    }
}

struct Rocket {
    rocket_name: String,
    rocket_type: String
}

impl Fly for Rocket {
    fn fly(&self) -> f64 {
        3000.0
    }

    fn display_name(&self) -> String {
        format!("{}[{}]", self.rocket_name, self.rocket_type)
    }
}

fn do_fly(fly_unit: &impl Fly) {
    println!("{} flying {} miles", fly_unit.display_name(), fly_unit.fly());
}

fn take_fly<T: Fly>(fly_unit: &T) {
    println!("{} flying {} miles", fly_unit.display_name(), fly_unit.fly());
}

fn duck_fly<T: Fly + Quack>(fly_unit: &T) {
    println!("{} flying {} miles.{}", fly_unit.display_name(), fly_unit.fly(), fly_unit.quack());
}

fn product_duck(name: &str) -> impl Fly + Quack {
    Bird{
        bird_name: String::from(name),
        bird_type: String::from("duck")
    }
}

fn trait_exercise() {
    let bird = product_duck("jole");
    let rocket = Rocket{
        rocket_name: String::from("hope"),
        rocket_type: String::from("rocket")
    };

    do_fly(&bird);
    duck_fly(&bird);
    take_fly(&rocket);
}

struct Point<X1, Y1> {
    x: X1,
    y: Y1,
}

impl<X1, Y1> Point<X1, Y1> {
    fn mix<X2, Y2>(self, new_point: Point<X2, Y2>) -> Point<X1, Y2>{
        Point {
            x: self.x,
            y: new_point.y
        }
    }
}
fn test_mix() {
    let p1 = Point {
        x: 1,
        y: 2.0
    };
    let result = p1.mix(Point { x: (true), y: ("test") });
    print!("x={}, y={}", result.x, result.y);
}

struct Response<T> {
    code: u8,
    msg: String,
    data: T
}

enum Time<T, E> {
    Hour(T),
    Minute(E)
}

fn test_generic_fn() {
    let resp = create_success_response("asfasdf");
    println!("{}", resp.data);
}

fn create_success_response<T>(data: T) -> Response<T> {
    Response {
        code: 200,
        msg: String::from("success"),
        data: data
    }
}

fn test_generic_struct() {
    let response = Response {
        code: 200,
        msg: String::from("success"),
        data: 50
    };
    println!("{}", response.data);
}

fn test_generic_enum() {
    let h: Time<u8, &str> = Time::Hour(53);
    if let Time::Hour(i) = h {
        println!("{}", i);
    }
}

fn read_file_name2() -> Result<String, std::io::Error> {
    let mut username_file = File::open("hello.txt")?;
    let mut user_name = String::new();

    username_file.read_to_string(&mut user_name)?;
    Ok(user_name)
}

fn read_file_name() -> Result<String, std::io::Error> {
    let greeting_file_result = File::open("hello.txt");

    let mut username_file = match greeting_file_result {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut user_name = String::new();

    match username_file.read_to_string(&mut user_name) {
        Ok(_) => Ok(user_name),
        Err(e) => Err(e),
    }
}

fn error_handle_exercise() {
    // panic!("first panic!");
}

struct Company {
    employees: Vec<Employee>
}

impl Company {
    fn add_employee(&mut self, name: &str, department: &str) {
        let employee = Employee {
            name: String::from(name),
            department: String::from(department)
        };
        self.employees.push(employee);
    }

    fn employees_in_department(&self, department: &str) -> Vec<&Employee> {
        let employees = &self.employees;
        let mut employees_in_department = Vec::new();

        for employee in employees {
            if department.eq(&employee.department) {
                employees_in_department.push(employee);
            }
        }

        employees_in_department
    }

    fn employee_map(&self) -> HashMap<&str, Vec<&Employee>> {
        let mut emp_map: HashMap<&str, Vec<&Employee>> = HashMap::new();
        let employees = &self.employees;
        for employee in employees {
            emp_map.entry(&employee.department[..]).and_modify(|employees| {employees.push(employee)}).or_insert(vec![employee]);
        }
        emp_map
    }

}

#[derive(Debug)]
struct Employee {
    name: String,
    department: String
}

fn test_company() {
    let mut company = Company {
        employees: Vec::new()
    };
    company.add_employee("joe", "chief");
    company.add_employee("cheer", "chief");
    company.add_employee("abi", "act");
    let chiefs = company.employees_in_department("chief");
    println!("{:?}", chiefs);
    let acts = company.employees_in_department("act");
    println!("{:?}", acts);

    let emp_map = company.employee_map();
    println!("{:?}", emp_map);
}

fn test_pig_latin() {
    pig_latin("first");
    pig_latin("apple");
    pig_latin("two");
}

fn pig_latin(str: &str) {
    let mut result = String::from(str);
    let vowel = vec!["a", "e", "i", "o", "u"];
    let first_consonant = &str[0..1];
    
    if vowel.contains(&first_consonant)  {
        result.push_str("-hay");
    } else {
        result.remove(0);
        result.push_str(first_consonant);
        result.push_str("-ay");
    }

    println!("{:?}", result);
}

fn test_find_mid_and_mode() {
    let list = vec![5, 5, 5, 5, 3, 3, 3, 1, 1, 2];
    let result = find_mid_and_mode(&list);
    println!("{:?}", result);
}

fn find_mid_and_mode(list: &Vec<i32>) -> Vec<i32> {
    // result vec
    let mut result: Vec<i32> = Vec::new();

    // sort vec
    let mut sorted_list: Vec<i32> = vec![0; list.len()];
    sorted_list.copy_from_slice(list);
    sorted_list.sort();
    // middle fo the sorted vec
    let len = sorted_list.len();
    let mid_index = len / 2;
    // push mid in result
    result.push(sorted_list[mid_index]);

    // mode
    let mut count_map = HashMap::new();
    for num in list {
        count_map.entry(num).and_modify(|cnt| { *cnt += 1 }).or_insert(1);
    }
    let mut most_often_cnt = 0;
    let mut most_ofen_num = 0;
    for (key, val) in count_map {
        if val > most_often_cnt {
            most_often_cnt = val;
            most_ofen_num = *key;
        }
    }
    // push mode in result
    result.push(most_ofen_num);

    return result;
}

fn common_collection_exercise() {
    let a = vec!["1", "2", "3"];
    println!("a = {}", a.get(1).expect(""));
    println!("a = {}", a[0]);
    let mut b: Vec<i32> = Vec::new();
    b.push(5);
    println!("b = {}", b.get(0).expect(""));
    // println!("b = {}", b[1]);

    // let c = HashMap!(String, String);

    let s = "1231232";
    let s1 = s.to_string();

    let f_val1 = String::from("val1");

    let mut hm = HashMap::new();
    hm.insert("key1", f_val1);
    println!("{}", hm.get("key1").expect(""));
    println!("{}", hm["key1"]);

    // for (key, value) in hm {
    //     println!("{}", key);
    //     println!("{}", value);
    // }
    hm.insert("key1", String::from("f_val1"));
    println!("{}", hm["key1"]);
    hm.entry("key1").or_insert(String::from("f_val2"));
    println!("{}", hm["key1"]);

    let text = "hello world wonderful world";
    let mut cnt_map = HashMap::new();
    for word in text.split_whitespace()  {
        let count = cnt_map.entry(word).or_insert(0);
        *count += 1;
    }
    println!("{:?}", cnt_map);
}

fn guide(key: &str) {
    match key {
        "guessing game" => gsgame::entry(),
        _ => ()
    }
}

struct User {
    active: bool,
    name: String,
    email: String,
    sign_in_count: u64,
}

fn struct_exercise() {
    let mut user = User {
        name: String::from("大壮"),
        email: String::from("qqq@999.com"),
        active: true,
        sign_in_count: 0
    };
    println!("user name = {}", user.name);
    user.active = false;
    println!("user active = {}", user.active);

    let mut b_user = build_user("joe", "qqe@999.com");
    println!("b_user name = {}", b_user.name);
    b_user.active = false;
    println!("b_user active = {}", b_user.active);
}

fn build_user(name: &str, email: &str) -> User {
    User {
        name: String::from(name),
        email: String::from(email),
        active: true,
        sign_in_count: 0
    }
}

fn slice_exercise()
{
    let mut str = String::from("hello world");
    let word = first_word(&str);

    // str.clear();

    println!("first_word = {word}");

    // let slice1 = &str[..];
    // let reference1 = &str;
    // let slice2 = &reference1[..];

    // println!("slice1 = {slice1} slice2 = {slice2}");
}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[..i];
        }
    }

    return &s[..];
}

fn ownership_fn_exercise() {
    let s1 = String::from("hello");
    let (s1, len) = caculate_length_tuple(s1);
    println!("The length of '{}' is {}.", s1, len);

    let mut s2 = String::from("hello world!");
    let s3: &String = &s2;
    println!("s3 is {}.", s3);
    {
        let p3 = &mut s2;
    }
    let p2 = &mut s2;
    let len2 = caculate_length(p2);
    println!("The length of '{}' is {}.", s2, len2);

    // let r1 = dangle();
}

// dangle reference.compile error!
// fn dangle() -> &String {
//     let str1 = String::from("s1");

//     &str1
// }

fn caculate_length(s: &mut String) -> usize {
    s.push_str("qweqwe");
    s.len()
}

fn caculate_length_tuple(s: String) -> (String, usize) {
    let length = s.len();
    (s, length)
}

fn ownership_exercise() {
    let p1 = String::from("param1");
    param_string(p1);
    // compile error!
    // println!("var is {p1}");
   
   let p2 = 6;
   param_int(p2);
   println!("var is {p2}");
}

fn param_string(str: String) {
    println!("param is {str}");
}

fn param_int(num: i32) {
    println!("param is {num}");
}

fn string_exercise() {
    // let mut s: String = String::from("sfsdfs");
    // s.push_str("12312312");
    // s.push('e');
    // println!("{s}");

    // let s1 = String::from("hello");
    // let s2 = s1.clone();
    // println!("{}", s2);
    // println!("{}", s1);

    // let x = 5;
    // let y = x;
    // println!("x = {}, y = {}", x, y);

    let s1 = String::from("hello, ");
    let s2 = String::from("world!");
    // let s3 = s1.add(&s2);
    let s3 = s1 + &s2;
    // println!("s1={s1}"); moved
    println!("s2={s2}");
    println!("s3={s3}");

    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");

    // let s = s1 + "-" + &s2 + "-" + &s3;

    let s = format!("{s1}-{s2}-{s3}");
    println!("{s}");
    println!("s1={s1}");

    let hello = "Здравствуйте";
    let answer = &hello[0..6];
    println!("{answer}");

    for c in hello.chars() {
        println!("{c}");
    }

    for c in hello.bytes() {
        println!("{c}");
    }
}

fn guessing_game() {
    ferris_say("猜数字!");

    let secret_number = rand::thread_rng().gen_range(1..=100);
    // println!("debug secret_number={secret_number}");
    
    loop {
        println!("答案的范围是[1-100], 请输入你猜测的数字。");

        let mut guess =  String::new();
        io::stdin()
            .read_line(&mut guess)
            .expect("读取输入失败！");
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        match guess.cmp(&secret_number) {
            Ordering::Equal => {
                println!("猜对啦！");
                break;
            },
            Ordering::Less => println!("太小了"),
            Ordering::Greater => println!("太大了"),
        }
    }
}

fn five() -> i32 {
    5
}

fn fn_exercise() {
    let x = five();
    println!("x={x}");

    let y = {
        let x1 = 6;
        x1 + 1
    };

    if y > 10 {
        println!("y={y}");
    }
}

fn ferris_say(msg: &str) {
    let stdout = stdout();
    let message = String::from(msg);
    let width = message.chars().count();

    let mut writer = BufWriter::new(stdout.lock());
    say(&message, width, &mut writer).unwrap();
}

fn arrya_err_exercise() {
    let months = ["January", "February", "March", "April", "May", "June", "July",
    "August", "September", "October", "November", "December"];

    println!("请输入月份数字，我将告诉你对应的英文单词");
    let mut index = String::new();
    io::stdin().read_line(&mut index).expect("faied to read line!");
    let index: usize = index.trim().parse().expect("请输入正确的数字！");

    let elment = months[index];
    println!("月份{index}对应的英文单词是{}", elment);
}

fn array_exercise() {
    let a = [1,2,3,4,5];
    for b in a {
        println!("{b}");
        println!("{}", a[0]);
    }

    let arr2: [&str; 5] = ["one", "two", "two2", "two3", "two5"];
    for b in arr2 {
        println!("{b}");
    }

    let arr3 = [6; 5];
    for b in arr3 {
        println!("{b}");
    }

    let arr6 = ["e"; 5];
    for b in arr6 {
        println!("{b}");
    }
}

fn tupler_exercise() {
    let x = (1, "2", 3.0);
    println!("the tuple is {}, {}, {}", x.0, x.1, x.2);

    let (a, b, c)  = x;
    println!("the destructuring  tuple is {a}, {b}, {c}");
}

fn shadow_exercise() {
    let x = 5;
    let x = x + 1;
    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}")
    }
    println!("The value of x is: {x}")
}
